﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Snowflake.Common
{
    /// <summary>
    /// This class provides functionality for Undo/Redo specified value
    /// </summary>
    /// <typeparam name="T">The type of the value that will restorable</typeparam>
    [Serializable]
    public class RestorableValue<T> : IRestorableValue
    {
        /// <summary>
        /// Orignal value
        /// </summary>
        protected T _OriginalValue;
        /// <summary>
        /// Current Value
        /// </summary>
        protected T _Value;
        /// <summary>
        /// It's true if the value is changed
        /// </summary>
        protected bool _HasChanges;
        /// <summary>
        /// The name of the value
        /// </summary>
        protected string _Name;

        public RestorableValue(string name, T value)
        {
            this._Name = name;
            this._Value = value;
            this._OriginalValue = default(T);
            this._HasChanges = false;
        }

        public RestorableValue()
            : this(null, default(T))
        {
        }
        public RestorableValue(T value)
            : this(null, value)
        {
        }

        public string Name
        {
            get { return this._Name; }
        }

        public bool HasChanges
        {
            get { return this._HasChanges; }
        }

        public T OriginalValue
        {
            get { return this._OriginalValue; }
        }


        public void AcceptChanges()
        {
            if (this._HasChanges)
            {
                this._OriginalValue = default(T);
                this._HasChanges = false;
            }
        }

        public void RejectChanges()
        {
            if (this._HasChanges)
            {
                this._Value = this._OriginalValue;
                this._OriginalValue = default(T);
                this._HasChanges = false;
            }
        }

        public static implicit operator T(RestorableValue<T> field)
        {
            return field.Value;
        }

        public static implicit operator RestorableValue<T>(T value)
        {
            return new RestorableValue<T>(value);
        }

        public virtual T Value
        {
            set
            {
                if (!Object.Equals(value, this._Value))
                {
                    if (!this._HasChanges)
                    {
                        this._OriginalValue = this._Value;
                        this._HasChanges = true;
                    }
                }

                this._Value = value;
            }
            get
            {
                return this._Value;
            }
        }

        object IRestorableValue.OriginalValue
        {
            get
            {
                return this._OriginalValue;
            }
        }

        object IRestorableValue.Value
        {
            set
            {
                this._Value = (T)value;
            }
            get
            {
                return this._Value;
            }
        }



    }
}
